const { UniCloudError, isUniPayError, ERROR } = require('../common/error');
/**
 * 商家付款功能
 */
const utils = require("./util.js")

const uniPay = require("uni-pay");

const configCenter = require("uni-config-center");

const config = configCenter({
	pluginId: 'uni-pay'
}).requireFile('config.js');

// const {
// 	UniCloudError,
// 	isUniPayError,
// 	ERROR
// } = require('../common/error')

const db = uniCloud.database();
const _ = db.command;

class ServiceBase {
	constructor(options) {
		// console.log("========",options);
		this.options = options

		if (!options.appId) throw new Error('appId required')
		if (!options.mchId) throw new Error('mchId required')
		if (!options.v3Key) throw new Error('v3Key required')
		if (!options.appPrivateKeyPath && !options.appPrivateKeyContent) throw new Error(
			'missing appPrivateKeyPath or appPrivateKeyContent')
		if (!options.appCertPath && !options.appCertContent) throw new Error(
			'missing appCertPath or appCertContent')
		// this._protocols = protocols
		this.platformCertificate = [] // 平台证书
		this._baseURL = 'https://api.mch.weixin.qq.com'

		this._cert = options.appCertPath ? utils.loadCertFromPath(options.appCertPath) : utils.loadCertFromContent(
			utils.formatKey(options.appCertContent, 'CERTIFICATE')
		)
		this._privateKey = options.appPrivateKeyPath ? utils.loadPrivateKeyFromPath(options.appPrivateKeyPath) :
			utils.loadPrivateKeyFromContent(
				utils.formatKey(options.appPrivateKeyContent, 'PRIVATE KEY')
			)
		// console.log("===>>>>>>",this._cert,this._privateKey);
	}
	/**
	 * 验证响应签名
	 * @param {Object} headers
	 * @param {Object} data
	 * @returns {Promise<void>}
	 * @private
	 */
	async _verifyResponseSign(headers, data = {}) {
		// 获取平台证书
		const platformCert = await this._getPlatformCert()

		const {
			'wechatpay-timestamp': wechatPayTimestamp,
			'wechatpay-nonce': wechatPayNonce,
			'wechatpay-signature': wechatPaySignature
		} = headers

		const signStr = [
			wechatPayTimestamp,
			wechatPayNonce,
			Object.keys(data).length ? JSON.stringify(data) : ''
		].reduce((sign, key) => {
			sign += key + '\n'
			return sign
		}, '')

		const verify = utils.rsaPublicKeyVerifySign(platformCert.certificate.publicKey.toPEM(), signStr,
			wechatPaySignature)
		if (!verify) throw new Error('response signature verification failed')
	}
	/**
	 * 获取微信支付平台证书
	 * 调用频率限制 1000次/s
	 * @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/wechatpay5_1.shtml
	 * @returns {Promise<*|*[]>}
	 * @private
	 */
	async _getPlatformCert() {
		if (this.platformCertificate.length <= 0) {
			const action = '/v3/certificates'
			const {
				status,
				data
			} = await uniCloud.httpclient.request(`${this._baseURL}${action}`, {
				method: 'GET',
				headers: {
					Accept: 'application/json',
					'content-type': 'application/json',
					Authorization: this._getAuthorization('GET', action)
				},
				dataType: 'json',
				// timeout: this.options.timeout
			})

			if (status !== 200) {
				throw new Error('request fail')
			}

			this.platformCertificate =data.data && data.data.reduce((res, cert) => {
				// 解密证书
				if (cert.encrypt_certificate) {
					const {
						nonce,
						associated_data: associatedData,
						ciphertext
					} = cert.encrypt_certificate
					const certContent = utils.decryptCiphertext(ciphertext, this.options.v3Key, nonce,
						associatedData)
					cert.certificate = utils.loadCertFromContent(certContent)
				}
				res.push(cert)
				return res
			}, []) || []
		}

		this.platformCertificate = this.platformCertificate.filter(item => new Date(item.expire_time).getTime() >
			Date.now())
		// console.log("this.platformCertificate", this.platformCertificate);
		return this.platformCertificate[0]
	}


	/**
	 * 生成 Authorization
	 * @param {String} method 请求方式
	 * @param {String} action URL
	 * @param {Object} body 请求体
	 * @returns {string}
	 * @private
	 */
	_getAuthorization(method = 'GET', action = '', body = {}) {
		const nonceStr = utils.getNonceStr()
		const timestamp = Date.parse(new Date()) / 1000
		const signStr = [
			method,
			method === 'GET' && Object.keys(body).length > 0 ? `${action}?${utils.getQueryStr(body)}` : action,
			timestamp,
			nonceStr,
			method === 'GET' ? '' : JSON.stringify(body)
		].reduce((sign, key) => {
			sign += key + '\n'
			return sign
		}, '')
		console.log("signStr======>>>>", signStr);
		const sign = utils.rsaPrivateKeySign(this._privateKey.toPEM(), signStr).toString('base64')
		const certSerialNo = this._cert.serialNumber.toUpperCase()

		return `WECHATPAY2-SHA256-RSA2048 mchid="${this.options.mchId}",nonce_str="${nonceStr}",signature="${sign}",timestamp="${timestamp}",serial_no="${certSerialNo}"`
	}
}
class service extends ServiceBase {
	constructor(obj) {
		super(obj)
	}
	/**
	 * 创建提现订单
	 */
	async createBatch(body = {}) {
		// 获取平台证书
		const platformCert = await this._getPlatformCert()
		const action = '/v3/transfer/batches'
		//获取body内容
		let bodyInfo = this.body_options(body)
		const certSerialNo = this._cert.serialNumber.toUpperCase()
		const Serial = utils.rsaPublicKeyEncryptData(certSerialNo, platformCert.certificate.publicKey.toPEM())
			.toString('base64')
		const headers = {
			Authorization: this._getAuthorization('POST', action, bodyInfo),
			Accept: 'application/json',
			'content-type': 'application/json',
			'Wechatpay-Serial': Serial
		}

		let url = `${this._baseURL}${action}`
		// uniCloud.httpProxyForEip.postJson(url: String, json?: Object, headers?: Object)
		let res = await uniCloud.httpProxyForEip.postJson(
			url,
			bodyInfo,
			headers
		)
		console.log("res++++++++++===========>>>>>>>>>", res);
		return res
	}
	/**
	 * 组合提现订单信息
	 */
	body_options(data = {}) {
		let userObj = {
			out_detail_no: data.order_id,
			transfer_amount: data.con_price,
			transfer_remark: "用户提现",
			openid: data.openid,
		}
		if (data.con_price > 150000) {
			userObj.user_name = data.name
		}
		let obj = {
			appid: this.options.appId,
			out_batch_no: data.out_batch_no,
			batch_name: "提现",
			batch_remark: "用户提现",
			total_amount: data.con_price,
			total_num: 1,
			transfer_detail_list: [userObj]
		}
		return obj
	}
	/**
	 * 查询提现订单状态
	 */
	async getBatchOrder(data) {
		let action =
			`/v3/transfer/batches/out-batch-no/${data.out_batch_no}/details/out-detail-no/${data.out_detail_no}`
		let method = "GET"
		const authorization = this._getAuthorization(method, action)
		let res = await uniCloud.httpclient.request(`${this._baseURL}${action}`, {
			method,
			headers: {
				Accept: 'application/json',
				'content-type': 'application/json',
				Authorization: authorization
			},
			dataType: 'json',
		})
		if (res.status !== 200) {
			// console.log(res);
			// throw new UniCloudError({
			// 	code: data.code,
			// 	message: data.message
			// })
		}
		console.log("res===>", res);
		return res
	}
}

function getUniPayConfig(data = {
	provider: "wxpay",
	provider_pay_type: "mp"
}) {
	let {
		provider,
		provider_pay_type,
	} = data;
	if (config && config[provider] && config[provider][provider_pay_type]) {
		let uniPayConfig = config[provider][provider_pay_type];
		if (!uniPayConfig.appId && provider !== "appleiap") {
			throw new Error(`uni-pay配置${provider}.${provider_pay_type}节点下的appId不能为空`);
		}
		return uniPayConfig;
	} else {
		throw new Error(`${provider}_${provider_pay_type} : 商户支付配置错误`);
	}
}

module.exports = new service(getUniPayConfig())